/*
Aircraft - An exercise in 3D rendering

TW Burger 10010087
ITEC 501
Technical University of British Columbia

November 27, 2001

 */

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

// applet class

public class a_aircraft_twburger extends java.applet.Applet implements
		KeyListener, MouseListener, MouseMotionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	int ScreenControl_V = 20;
	int controlH = 80;
	int controlV = 20;
	int ch_offsets[] = new int[6];
	int topline = 15;

	int dh, dv;
	Image buf;
	Graphics gbuf;
	boolean axisswitch = true;
	boolean squadswitch = false;
	boolean hasfocus = false;

	XYZAxis xyzaxis = new XYZAxis();
	AnAircraft Aircraft = new AnAircraft();
	double transform[] = new double[18];

	double xrot = 110, yrot = 10, zrot = 110;
	double dispsize = 100;
	double dispsize0 = 100;
	double imgdistance = 100;
	double mx0 = 0;
	double my0 = 0;
	double axrot = 0, ayrot = 0, azrot = 0; // aircraft values
	double caxrot = 0, cayrot = 0, cazrot = 0; // cummulative values for display
	Point3D center = new Point3D(0.0, 0.0, 0.0); // default center point
	Font f = new Font("TimesRoman", Font.PLAIN, 12);

	Point3D factor = new Point3D(0.0, 0.0, 0.0); // default sizing factors

	private Checkbox ivjAxisDisplay = null;
	private Scrollbar ivjScrollDistance = null;
	private Scrollbar ivjScrollSize = null;
	private Scrollbar ivjScrollPitch = null;
	private Scrollbar ivjScrollRoll = null;
	private Scrollbar ivjScrollYaw = null;
	IvjEventHandler ivjEventHandler = new IvjEventHandler();

	int lastpitchvalue = 0;
	int lastrollvalue = 0;
	int lastyawvalue = 0;
	int lastsizevalue = 0;
	int lastdistvalue = 0;

	public static void main(java.lang.String[] args) {
		try {
			Frame frame = new java.awt.Frame();
			a_aircraft_twburger aa_aircraft_twburger;
			// Class iiCls = Class.forName("a_aircraft_twburger");
			// Class<?> iiCls = Class.forName("a_aircraft_twburger");
			@SuppressWarnings("unchecked")
			Class<Applet> iiCls = (Class<Applet>) Class
					.forName("a_aircraft_twburger");
			ClassLoader iiClsLoader = iiCls.getClassLoader();
			aa_aircraft_twburger = (a_aircraft_twburger) java.beans.Beans
					.instantiate(iiClsLoader, "a_aircraft_twburger");
			frame.add("Center", aa_aircraft_twburger);
			frame.setSize(aa_aircraft_twburger.getSize());
			frame.addWindowListener(new java.awt.event.WindowAdapter() {
				public void windowClosing(java.awt.event.WindowEvent e) {
					System.exit(0);
				};
			});
			// frame.show();
			java.awt.Insets insets = frame.getInsets();
			frame.setSize(frame.getWidth() + insets.left + insets.right,
					frame.getHeight() + insets.top + insets.bottom);
			frame.setVisible(true);

		} catch (Throwable exception) {
			System.err
					.println("Exception occurred in main() of java.applet.Applet");
			exception.printStackTrace(System.out);
		}
	}

	public void keyPressed(KeyEvent evt) {
		
		int nKey = evt.getKeyChar();
		
		nKey = Character.toUpperCase(nKey);
		
		boolean fRepaint = false;

		if ('S' == nKey) {
			squadswitch = !squadswitch;
			fRepaint = true;
		} else if ('X' == nKey) {
			axisswitch = !axisswitch;
			ivjAxisDisplay.setState(axisswitch);
			fRepaint = true;
		} else {
			if (evt.isControlDown()) {
				int change = 2;
				if (evt.isShiftDown()) {
					change = 10;
				}

				switch (evt.getKeyCode()) {
				// change X Y and Z rotation angles for the fixed axis
				// Cumulative due to change being made on each drawing
				case KeyEvent.VK_KP_UP:
				case KeyEvent.VK_UP:
					fRepaint = true;
					xrot -= change;
					break;

				case KeyEvent.VK_KP_DOWN:
				case KeyEvent.VK_DOWN:
					fRepaint = true;
					xrot += change;
					break;

				case KeyEvent.VK_KP_RIGHT:
				case KeyEvent.VK_RIGHT:
					fRepaint = true;
					zrot -= change;
					break;

				case KeyEvent.VK_KP_LEFT:
				case KeyEvent.VK_LEFT:
					fRepaint = true;
					zrot += change;
					break;

				case KeyEvent.VK_PAGE_UP:
					fRepaint = true;
					yrot += change;
					break;

				case KeyEvent.VK_PAGE_DOWN:
					fRepaint = true;
					yrot -= change;
					break;
				}
			} else {
				int change = 2;
				if (evt.isShiftDown()) {
					change = 10;
				}

				switch (evt.getKeyCode()) {
				// change X Y and Z rotation angles for the fixed axis
				// Cumulative due to change being made on each drawing

				case KeyEvent.VK_KP_UP:
				case KeyEvent.VK_UP:
					fRepaint = true;
					azrot = change;
					break;

				case KeyEvent.VK_KP_DOWN:
				case KeyEvent.VK_DOWN:
					fRepaint = true;
					azrot = -change;
					break;

				case KeyEvent.VK_KP_RIGHT:
				case KeyEvent.VK_RIGHT:
					fRepaint = true;
					axrot = change;
					break;

				case KeyEvent.VK_KP_LEFT:
				case KeyEvent.VK_LEFT:
					fRepaint = true;
					axrot = -change;
					break;

				case KeyEvent.VK_PAGE_UP:
					fRepaint = true;
					ayrot = change;
					break;

				case KeyEvent.VK_PAGE_DOWN:
					fRepaint = true;
					ayrot = -change;
					break;
				}
			}
		}

		if (fRepaint) {
			reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot,
					dispsize, transform);
			repaint();
		}

		//super.processKeyEvent(evt);
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}

	class IvjEventHandler implements java.awt.event.AdjustmentListener,
			java.awt.event.ItemListener {
		public void adjustmentValueChanged(java.awt.event.AdjustmentEvent e) {
			if (e.getSource() == a_aircraft_twburger.this.getScrollSize())
				connEtoC1();
			if (e.getSource() == a_aircraft_twburger.this.getScrollDistance())
				connEtoC2();
			if (e.getSource() == a_aircraft_twburger.this.getScrollYaw())
				connEtoC3();
			if (e.getSource() == a_aircraft_twburger.this.getScrollRoll())
				connEtoC4();
			if (e.getSource() == a_aircraft_twburger.this.getScrollPitch())
				connEtoC5();
			if (e.getSource() == a_aircraft_twburger.this.getAxisDisplay())
				connEtoC6();
		};

		public void itemStateChanged(java.awt.event.ItemEvent e) {
			if (e.getSource() == a_aircraft_twburger.this.getAxisDisplay())
				connEtoC6();
		};

	};

	class Point2D {
		int x, y;

		Point2D(int x, int y) {
			this.x = x;
			this.y = y;
		}

		Point2D(Point2D p) {
			this.x = p.x;
			this.y = p.y;
		}
	};

	class Point3D {
		double x, y, z;

		Point3D(double x, double y, double z) {
			this.x = x;
			this.y = y;
			this.z = z;
		}

		void set(double x, double y, double z) {
			this.x = x;
			this.y = y;
			this.z = z;
		}
	};

	/*
	 * class Vector { Point3D p1, p2; Vector( Point2D Point2D p1, Point2D p2 ) {
	 * this.p1=p1; this.p2=p2; } };
	 */

	/*
	 * This is the axis of the aircraft not the screen
	 */

	class XYZAxis {
		Point3D axis[] = null;

		XYZAxis() {
			axis = new Point3D[3];

			axis[0] = new Point3D(1, 0, 0);
			axis[1] = new Point3D(0, 1, 0);
			axis[2] = new Point3D(0, 0, 1);
		}

		// rotate the axis
		void rotate() {
			this.axis[0] = ArbitraryRotate(this.axis[0], transform[16],
					this.axis[1]);
			this.axis[0] = ArbitraryRotate(this.axis[0], transform[17],
					this.axis[2]);

			this.axis[1] = ArbitraryRotate(this.axis[1], transform[15],
					this.axis[0]);
			this.axis[1] = ArbitraryRotate(this.axis[1], transform[17],
					this.axis[2]);

			this.axis[2] = ArbitraryRotate(this.axis[2], transform[15],
					this.axis[0]);
			this.axis[2] = ArbitraryRotate(this.axis[2], transform[16],
					this.axis[1]);
		}

		void draw(Graphics gbuf) {
			Point2D p0;
			Point2D p1;

			p0 = xform_3to2d(center, transform, factor, 1.0);
			for (int i = 0; i < 3; i++) {
				p1 = xform_3to2d(this.axis[i], transform, factor, 1.0);
				gbuf.drawLine(p0.x, p0.y, p1.x, p1.y);
				switch (i) {
				case 0:
					gbuf.drawString("X", p1.x, p1.y);
					break;
				case 1:
					gbuf.drawString("Y", p1.x, p1.y);
					break;
				case 2:
					gbuf.drawString("Z", p1.x, p1.y);
					break;
				}
			}
		}
	};

	/*
	 * This is a collection of triangles self defining and self drawing
	 */

	class AnAircraft {
		Point3D p[] = null;
		int number = 0;

		AnAircraft() {
			number = 15;
			p = new Point3D[number];

			p[0] = new Point3D(.8, 0, 0);
			p[1] = new Point3D(.2, .05, .8);
			p[2] = new Point3D(.2, .05, -.8);

			p[3] = new Point3D(.8, 0, 0);
			p[4] = new Point3D(.2, -.05, .8);
			p[5] = new Point3D(.2, -.05, -.8);

			p[6] = new Point3D(.2, .05, 0);
			p[7] = new Point3D(.2, .3, 0);
			p[8] = new Point3D(.4, .03, 0);

			p[9] = new Point3D(.2, .05, .8);
			p[10] = new Point3D(.2, -.05, .8);
			p[11] = new Point3D(.2, -.05, .7);

			p[12] = new Point3D(.2, .05, -.8);
			p[13] = new Point3D(.2, -.05, -.8);
			p[14] = new Point3D(.2, -.05, -.7);
		}

		// aircraft rotation
		void rotate() {
			for (int i = 0; i < number; i++) {
				p[i] = ArbitraryRotate(p[i], transform[15], xyzaxis.axis[0]);
				p[i] = ArbitraryRotate(p[i], transform[16], xyzaxis.axis[1]);
				p[i] = ArbitraryRotate(p[i], transform[17], xyzaxis.axis[2]);
			}
		}

		void draw(Graphics gbuf, boolean Squadran) {
			if (Squadran) {
				Point3D squadfactor = new Point3D(0, 0, 0);
				drawTriangles(this.p, this.number / 3, gbuf, squadfactor, .33);
				squadfactor.set(-1.9, 1.9, 1.9);
				drawTriangles(this.p, this.number / 3, gbuf, squadfactor, .33);
				squadfactor.set(-1.9, 1.9, -1.9);
				drawTriangles(this.p, this.number / 3, gbuf, squadfactor, .33);
			} else
				drawTriangles(this.p, this.number / 3, gbuf, factor, 1.0);
		}

		void drawTriangles(Point3D p[], int count, Graphics gbuf,
				Point3D factor, double objdispsize) {
			for (int i = 0; i < count; i++) {
				Point2D ps;
				Point2D p0;
				Point2D p1 = null;
				// set the first point
				ps = xform_3to2d(p[i * 3], transform, factor, objdispsize);
				p0 = new Point2D(ps);
				for (int j = 1; j < 3; j++) {
					p1 = xform_3to2d(p[i * 3 + j], transform, factor,
							objdispsize);
					gbuf.drawLine(p0.x, p0.y, p1.x, p1.y);
					p0 = p1;
				}
				gbuf.drawLine(p1.x, p1.y, ps.x, ps.y);
			}
		}

	};

	/*
	 * Rotate a point pxyz by angle theta around an arbitrary axis rxyz. This
	 * spins the plane on its own axis.
	 */

	Point3D ArbitraryRotate(Point3D pxyz, double theta, Point3D rxyz) {
		double px = pxyz.x;
		double py = pxyz.y;
		double pz = pxyz.z;

		double rx = rxyz.x;
		double ry = rxyz.y;
		double rz = rxyz.z;

		double qx = 0;
		double qy = 0;
		double qz = 0;

		double costheta, sintheta;
		theta = theta * Math.PI / 180.0;

		costheta = Math.cos(theta);
		sintheta = Math.sin(theta);

		qx += (costheta + (1 - costheta) * rx * rx) * px;
		qx += ((1 - costheta) * rx * ry - rz * sintheta) * py;
		qx += ((1 - costheta) * rx * rz + ry * sintheta) * pz;

		qy += ((1 - costheta) * rx * ry + rz * sintheta) * px;
		qy += (costheta + (1 - costheta) * ry * ry) * py;
		qy += ((1 - costheta) * ry * rz - rx * sintheta) * pz;

		qz += ((1 - costheta) * rx * rz - ry * sintheta) * px;
		qz += ((1 - costheta) * ry * rz + rx * sintheta) * py;
		qz += (costheta + (1 - costheta) * rz * rz) * pz;

		return (new Point3D(qx, qy, qz));
	}

	/*
	 * Key hits are only detected when the applet has focus from a mouse click.
	 */
/*
	@Override
	protected void processKeyEvent(KeyEvent evt) {

		if (evt.getID() != KeyEvent.KEY_PRESSED)
			return; // Only handle the one event

		int nKey = Character.toUpperCase(evt.getKeyChar());
		boolean fRepaint = false;

		if ('S' == nKey) {
			squadswitch = !squadswitch;
			fRepaint = true;
		} else if ('X' == nKey) {
			axisswitch = !axisswitch;
			ivjAxisDisplay.setState(axisswitch);
			fRepaint = true;
		} else {
			if (evt.isControlDown()) {
				int change = 2;
				if (evt.isShiftDown()) {
					change = 10;
				}

				switch (nKey) {
				// change X Y and Z rotation angles for the fixed axis
				// Cumulative due to change being made on each drawing
				case Event.UP:
					fRepaint = true;
					xrot += change;
					break;

				case Event.DOWN:
					fRepaint = true;
					xrot -= change;
					break;

				case Event.RIGHT:
					fRepaint = true;
					zrot -= change;
					break;

				case Event.LEFT:
					fRepaint = true;
					zrot += change;
					break;

				case Event.PGUP:
					// fRepaint = true;
					// yrot += change;
					break;

				case Event.PGDN:
					// fRepaint = true;
					// yrot -= change;
					break;
				}
			} else {
				int change = 2;
				if (evt.isShiftDown()) {
					change = 10;
				}

				switch (nKey) {
				// change X Y and Z rotation angles for the fixed axis
				// Cumulative due to change being made on each drawing

				case Event.RIGHT:
					fRepaint = true;
					axrot = change;
					break;

				case Event.LEFT:
					fRepaint = true;
					axrot = -change;
					break;

				case Event.UP:
					fRepaint = true;
					azrot = -change;
					break;

				case Event.DOWN:
					fRepaint = true;
					azrot = change;
					break;

				case Event.PGUP:
					fRepaint = true;
					ayrot = change;
					break;

				case Event.PGDN:
					fRepaint = true;
					ayrot = -change;
					break;
				}
			}
		}

		if (fRepaint) {
			reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot,
					dispsize, transform);
			repaint();
		}

		super.processKeyEvent(evt);

		return;
	}
*/

	/*
	 * public boolean keyDown(Event evt, int nKey) { boolean fRepaint = false;
	 * 
	 * if( 'S' == nKey || 's' == nKey ) { squadswitch = !squadswitch; fRepaint =
	 * true; } else if( 'X' == nKey || 'x' == nKey ) { axisswitch = !axisswitch;
	 * ivjAxisDisplay.setState( axisswitch); fRepaint = true; } else { if
	 * (evt.controlDown()) { int change = 2; if (evt.shiftDown()) { change = 10;
	 * }
	 * 
	 * switch (nKey) { // change X Y and Z rotation angles for the fixed axis //
	 * cummulative due to change being made on each drawing case Event.UP:
	 * fRepaint = true; xrot += change; break;
	 * 
	 * case Event.DOWN: fRepaint = true; xrot -= change; break;
	 * 
	 * case Event.RIGHT: fRepaint = true; zrot -= change; break;
	 * 
	 * case Event.LEFT: fRepaint = true; zrot += change; break;
	 * 
	 * case Event.PGUP: //fRepaint = true; //yrot += change; break;
	 * 
	 * case Event.PGDN: //fRepaint = true; //yrot -= change; break; } } else {
	 * int change = 2; if (evt.shiftDown()) { change = 10; }
	 * 
	 * switch (nKey) { // change X Y and Z rotation angles for the fixed axis //
	 * cummulative due to change being made on each drawing
	 * 
	 * case Event.RIGHT: fRepaint = true; axrot = change; break;
	 * 
	 * case Event.LEFT: fRepaint = true; axrot = -change; break;
	 * 
	 * case Event.UP: fRepaint = true; azrot = -change; break;
	 * 
	 * case Event.DOWN: fRepaint = true; azrot = change; break;
	 * 
	 * case Event.PGUP: fRepaint = true; ayrot = change; break;
	 * 
	 * case Event.PGDN: fRepaint = true; ayrot = -change; break; } } }
	 * 
	 * 
	 * if ( fRepaint ) { reset_coords(center, xrot, yrot, zrot, axrot, ayrot,
	 * azrot, dispsize, transform); repaint(); }
	 * 
	 * return fRepaint; }
	 */

	/*
	 * The mouse click resets drag detection
	 */

	@Override
	public void mouseClicked(MouseEvent evt) {

	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent evt) {
				
		// we have focus

		if (!hasfocus) {
			repaint();
			hasfocus = true;
		}

		// save current mouse pos and magnification
		mx0 = evt.getX();
		my0 = evt.getY();
		
		dispsize0 = dispsize;

		return;
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	/*
	public boolean mouseDown(Event evt, int x, int y) {

		// we have focus

		if (!hasfocus) {
			repaint();
			hasfocus = true;
		}

		// save current mouse pos and magnification
		mx0 = x;
		my0 = y;
		dispsize0 = dispsize;

		return true;
	}
	*/
	
	/*
	 * Handle dragging for screen rotation or zoom
	 */

	//public boolean mouseDrag(Event evt, int x, int y) {
	
	public void mouseDragged(MouseEvent evt) {
		// zooming
		if (evt.isShiftDown()) {

			// get ratio of current pos wrt clicked pos

			double dx = mx0 - dh / 2;
			double dy = my0 - dv / 2;
			double r1 = Math.sqrt(dx * dx + dy * dy);
			dx = evt.getX() - dh / 2;
			dy = evt.getY() - dv / 2;
			double r2 = Math.sqrt(dx * dx + dy * dy);

			// reset magnification

			dispsize = r2 / r1 * dispsize0;
		}

		// rotation

		else {

			// change X Y and Z rotation angles

			if (evt.isControlDown()) {
				ayrot = evt.getY() - my0;
				azrot = evt.getX() - mx0;
			} else {
				xrot += evt.getY() - my0;
				zrot += evt.getX() - mx0;
			}
			my0 = evt.getY();
			mx0 = evt.getX();
		}

		// update coords and redraw

		reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot, dispsize,
				transform);
		repaint();

		return;
	}

	public void mouseMoved(MouseEvent evt) {
		
	}

	public void init() {
		try {
			// create offscreen drawing
			super.init();
			setName("a_aircraft_twburger");
			setLayout(null);
			setSize(600, 600);

			dh = this.getSize().width;
			dv = this.getSize().height;

			// control horizontal offsets
			int offset = dh / 6;
			int gap = 2;
			ch_offsets[0] = offset / 2;
			for (int i = 1; i < 6; i++)
				ch_offsets[i] = gap + controlH + ch_offsets[i - 1];

			buf = createImage(dh, dv);
			gbuf = buf.getGraphics();

			// set up initial 3d coordinates
			reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot,
					dispsize, transform);

			add(getScrollYaw(), getScrollYaw().getName());
			add(getScrollPitch(), getScrollPitch().getName());
			add(getScrollRoll(), getScrollRoll().getName());
			add(getScrollSize(), getScrollSize().getName());
			add(getScrollDistance(), getScrollDistance().getName());
			add(getAxisDisplay(), getAxisDisplay().getName());

			ivjAxisDisplay.setState(axisswitch);
			ivjScrollPitch.setValue(0);
			ivjScrollRoll.setValue(0);
			ivjScrollYaw.setValue(0);

			initConnections();

			addKeyListener( this );
			addMouseListener( this );
			addMouseMotionListener(this);
			
			setFocusable(true);
			

		} catch (java.lang.Throwable ivjExc) {
			// user code begin {2}
			// user code end
			handleException(ivjExc);
		}
	}

	public void paint(Graphics g) {
		gbuf.setColor(Color.black);
		gbuf.fillRect(0, 0, dh, dv);
		gbuf.setFont(f);

		gbuf.setColor(Color.white);

		// draw xrot, zrot, dispsize strings
		caxrot += axrot;
		cayrot += ayrot;
		cazrot += azrot;
		gbuf.drawString("Roll = " + String.valueOf(caxrot), ch_offsets[0],
				topline);
		gbuf.drawString("Yaw = " + String.valueOf(cayrot), ch_offsets[1],
				topline);
		gbuf.drawString("Pitch = " + String.valueOf(cazrot), ch_offsets[2],
				topline);
		gbuf.drawString(
				"Size % = "
						+ String.valueOf((double) Math.round(dispsize * 100) / 100),
				ch_offsets[3], topline);
		gbuf.drawString(
				"Distance % = "
						+ String.valueOf((double) Math.round(imgdistance * 100) / 100),
				ch_offsets[4], topline);

		// Key hits are only detected when the applet has focus from a mouse
		// click.
		if (!hasfocus)
			gbuf.drawString("Click with the mouse to start", dh / 2 - 75,
					dv / 2);
		else {
			// gbuf.drawString("(Up-Down Pitch) (Left-Right Roll) (PgUp-PgDn Yaw) / Shift Fast / Shift-Drag Zooms / X - Axis on-off",
			// 2, dv - 15 );

			// rotate the display
			xyzaxis.rotate();
			Aircraft.rotate();

			gbuf.setColor(Color.yellow);

			// Draw the screen rotations
			gbuf.drawString("X = " + String.valueOf(xrot), 2, 80);
			gbuf.drawString("Y = " + String.valueOf(yrot), 2, 94);
			gbuf.drawString("Z = " + String.valueOf(zrot), 2, 108);

			// draw the display
			if (axisswitch) {
				xyzaxis.draw(gbuf);
			}
			// draw the airplane
			gbuf.setColor(Color.red);
			Aircraft.draw(gbuf, squadswitch);

			axrot = 0;
			ayrot = 0;
			azrot = 0; // reset to get next value
		}

		// copy to screen
		g.drawImage(buf, 0, 0, this);
	}

	/*
	 * Coordinate transformation data structure - updates the transform based on
	 * current xrot, zrot, dispsize values.
	 */

	public void reset_coords(Point3D p, double xrot, double yrot, double zrot,
			double axrot, double ayrot, double azrot, double dispsize,
			double transform[]) {
		transform[0] = p.x;
		transform[1] = p.y;
		transform[2] = p.z;
		transform[3] = dispsize;

		transform[4] = dh / 2.0;
		transform[5] = dv / 2.0;

		double cos_xrot = Math.cos(xrot * Math.PI / 180.0);
		double sin_xrot = Math.sin(xrot * Math.PI / 180.0);

		double cos_yrot = Math.cos(yrot * Math.PI / 180.0);
		double sin_yrot = Math.sin(yrot * Math.PI / 180.0);

		double cos_zrot = Math.cos(zrot * Math.PI / 180.0);
		double sin_zrot = Math.sin(zrot * Math.PI / 180.0);

		transform[6] = sin_zrot;
		transform[7] = cos_zrot;

		transform[8] = -sin_xrot * cos_zrot;
		transform[9] = sin_xrot * sin_zrot;
		transform[10] = cos_xrot;

		transform[11] = cos_yrot;
		transform[12] = sin_yrot;

		transform[15] = axrot;
		transform[16] = ayrot;
		transform[17] = azrot;
	}

	/*
	 * Overload the applet function update to create a no flicker display.
	 */

	public void update(Graphics g) {
		paint(g);
	}

	/*
	 * Transform 3d to 2d by matrix multiplication. This does a combined
	 * adjustment to the 3D values and calculation of the 2D representation.
	 */

	public Point2D xform_3to2d(Point3D p3d, double transform[], Point3D factor,
			double magx) {
		double x, y, z;

		x = p3d.x + factor.x; // offset by the factor
		y = p3d.y + factor.y;
		z = p3d.z + factor.z;

		// set the magnitude
		x = (x - transform[0]) * transform[3] * magx * imgdistance / 100;
		y = (y - transform[1]) * transform[3] * magx * imgdistance / 100;
		z = (z - transform[2]) * transform[3] * magx * imgdistance / 100;

		// create the 2D coordinate to plot
		int nx = (int) (transform[4] + transform[6] * x + transform[7] * y);
		int ny = (int) (transform[5] - transform[8] * x - transform[9] * y - transform[10]
				* z);

		return (new Point2D(nx, ny));
	}

	private java.awt.Checkbox getAxisDisplay() {
		if (ivjAxisDisplay == null) {
			try {
				ivjAxisDisplay = new java.awt.Checkbox();
				ivjAxisDisplay.setName("AxisDisplay");
				ivjAxisDisplay.setBounds(ch_offsets[5], ScreenControl_V,
						controlH + 15, controlV);
				ivjAxisDisplay.setLabel("Display Axis");
				// user code begin {1}
				// user code end
			} catch (java.lang.Throwable ivjExc) {
				// user code begin {2}
				// user code end
				handleException(ivjExc);
			}
		}
		return ivjAxisDisplay;
	}

	private java.awt.Scrollbar getScrollDistance() {
		if (ivjScrollDistance == null) {
			try {
				ivjScrollDistance = new java.awt.Scrollbar();
				ivjScrollDistance.setName("ScrollDistance");
				ivjScrollDistance.setMaximum(101);
				ivjScrollDistance.setMinimum(-100);
				ivjScrollDistance.setVisibleAmount(1);
				ivjScrollDistance.setBounds(ch_offsets[4], ScreenControl_V,
						controlH, controlV);
				ivjScrollDistance.setOrientation(java.awt.Scrollbar.HORIZONTAL);
				// user code begin {1}
				// user code end
			} catch (java.lang.Throwable ivjExc) {
				// user code begin {2}
				// user code end
				handleException(ivjExc);
			}
		}
		return ivjScrollDistance;
	}

	private java.awt.Scrollbar getScrollSize() {
		if (ivjScrollSize == null) {
			try {
				ivjScrollSize = new java.awt.Scrollbar();
				ivjScrollSize.setName("ScrollSize");
				ivjScrollSize.setMaximum(101);
				ivjScrollSize.setMinimum(-100);
				ivjScrollSize.setVisibleAmount(1);
				ivjScrollSize.setBounds(ch_offsets[3], ScreenControl_V,
						controlH, controlV);
				ivjScrollSize.setOrientation(java.awt.Scrollbar.HORIZONTAL);
				// user code begin {1}
				// user code end
			} catch (java.lang.Throwable ivjExc) {
				// user code begin {2}
				// user code end
				handleException(ivjExc);
			}
		}
		return ivjScrollSize;
	}

	private java.awt.Scrollbar getScrollPitch() {
		if (ivjScrollPitch == null) {
			try {
				ivjScrollPitch = new java.awt.Scrollbar();
				ivjScrollPitch.setName("ScrollPitch");
				ivjScrollPitch.setMaximum(361);
				ivjScrollPitch.setMinimum(-360);
				ivjScrollPitch.setVisibleAmount(1);
				ivjScrollPitch.setBounds(ch_offsets[2], ScreenControl_V,
						controlH, controlV);
				ivjScrollPitch.setOrientation(java.awt.Scrollbar.HORIZONTAL);
				// user code begin {1}
				// user code end
			} catch (java.lang.Throwable ivjExc) {
				// user code begin {2}
				// user code end
				handleException(ivjExc);
			}
		}
		return ivjScrollPitch;
	}

	private java.awt.Scrollbar getScrollYaw() {
		if (ivjScrollYaw == null) {
			try {
				ivjScrollYaw = new java.awt.Scrollbar();
				ivjScrollYaw.setName("ScrollYaw");
				ivjScrollYaw.setMaximum(361);
				ivjScrollYaw.setMinimum(-360);
				ivjScrollYaw.setVisibleAmount(1);
				ivjScrollYaw.setBounds(ch_offsets[1], ScreenControl_V,
						controlH, controlV);
				ivjScrollYaw.setOrientation(java.awt.Scrollbar.HORIZONTAL);
				// user code begin {1}
				// user code end
			} catch (java.lang.Throwable ivjExc) {
				// user code begin {2}
				// user code end
				handleException(ivjExc);
			}
		}
		return ivjScrollYaw;
	}

	private java.awt.Scrollbar getScrollRoll() {
		if (ivjScrollRoll == null) {
			try {
				ivjScrollRoll = new java.awt.Scrollbar();
				ivjScrollRoll.setName("ScrollRoll");
				ivjScrollRoll.setMaximum(361);
				ivjScrollRoll.setMinimum(-360);
				ivjScrollRoll.setVisibleAmount(1);
				ivjScrollRoll.setBounds(ch_offsets[0], ScreenControl_V,
						controlH, controlV);
				ivjScrollRoll.setOrientation(java.awt.Scrollbar.HORIZONTAL);
				// user code begin {1}
				// user code end
			} catch (java.lang.Throwable ivjExc) {
				// user code begin {2}
				// user code end
				handleException(ivjExc);
			}
		}
		return ivjScrollRoll;
	}

	private void initConnections() throws java.lang.Exception {
		// user code begin {1}
		// user code end
		getScrollSize().addAdjustmentListener(ivjEventHandler);
		getScrollDistance().addAdjustmentListener(ivjEventHandler);
		getScrollYaw().addAdjustmentListener(ivjEventHandler);
		getScrollRoll().addAdjustmentListener(ivjEventHandler);
		getScrollPitch().addAdjustmentListener(ivjEventHandler);
		getAxisDisplay().addItemListener(ivjEventHandler);
	}

	public void scrollPitch_AdjustmentEvents() {

		int val = ivjScrollPitch.getValue();

		azrot = val - lastpitchvalue;
		lastpitchvalue = val;

		reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot, dispsize,
				transform);
		repaint();
		return;
	}

	public void scrollRoll_AdjustmentEvents() {
		int val = ivjScrollRoll.getValue();

		axrot = val - lastrollvalue;
		lastrollvalue = val;

		reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot, dispsize,
				transform);
		repaint();
		return;
	}

	public void scrollYaw_AdjustmentEvents() {
		int val = ivjScrollYaw.getValue();

		ayrot = val - lastyawvalue;
		lastyawvalue = val;

		reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot, dispsize,
				transform);
		repaint();
		return;
	}

	public void scrollSize_AdjustmentEvents() {
		int val = ivjScrollSize.getValue();

		dispsize += val - lastsizevalue;
		lastsizevalue = val;

		reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot, dispsize,
				transform);
		repaint();
		return;
	}

	public void scrollDistance_AdjustmentEvents() {
		int val = ivjScrollDistance.getValue();

		imgdistance -= val - lastdistvalue;
		lastdistvalue = val;

		reset_coords(center, xrot, yrot, zrot, axrot, ayrot, azrot, dispsize,
				transform);
		repaint();
		return;
	}

	public void axisDisplay_ItemEvents() {

		axisswitch = ivjAxisDisplay.getState();
		repaint();

		return;
	}

	private void connEtoC1() {
		try {
			// user code begin {1}
			// user code end
			this.scrollSize_AdjustmentEvents();
			// user code begin {2}
			// user code end
		} catch (java.lang.Throwable ivjExc) {
			// user code begin {3}
			// user code end
			handleException(ivjExc);
		}
	}

	private void connEtoC2() {
		try {
			// user code begin {1}
			// user code end
			this.scrollDistance_AdjustmentEvents();
			// user code begin {2}
			// user code end
		} catch (java.lang.Throwable ivjExc) {
			// user code begin {3}
			// user code end
			handleException(ivjExc);
		}
	}

	private void connEtoC3() {
		try {
			// user code begin {1}
			// user code end
			this.scrollYaw_AdjustmentEvents();
			// user code begin {2}
			// user code end
		} catch (java.lang.Throwable ivjExc) {
			// user code begin {3}
			// user code end
			handleException(ivjExc);
		}
	}

	private void connEtoC4() {
		try {
			// user code begin {1}
			// user code end
			this.scrollRoll_AdjustmentEvents();
			// user code begin {2}
			// user code end
		} catch (java.lang.Throwable ivjExc) {
			// user code begin {3}
			// user code end
			handleException(ivjExc);
		}
	}

	private void connEtoC5() {
		try {
			// user code begin {1}
			// user code end
			this.scrollPitch_AdjustmentEvents();
			// user code begin {2}
			// user code end
		} catch (java.lang.Throwable ivjExc) {
			// user code begin {3}
			// user code end
			handleException(ivjExc);
		}
	}

	private void connEtoC6() {
		try {
			// user code begin {1}
			// user code end
			this.axisDisplay_ItemEvents();
			// user code begin {2}
			// user code end
		} catch (java.lang.Throwable ivjExc) {
			// user code begin {3}
			// user code end
			handleException(ivjExc);
		}
	}

	private void handleException(java.lang.Throwable exception) {

		/* Uncomment the following lines to print uncaught exceptions to stdout */
		System.out.println("--------- UNCAUGHT EXCEPTION ---------");
		exception.printStackTrace(System.out);
	}


} // end of class
